<meta charset="utf-8">
<title>CSSNumericValue.to tests</title>
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-cssnumericvalue-to">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../resources/testhelper.js"></script>
<script>
'use strict';

test(() => {
  assert_throws_dom("SyntaxError", () => CSS.px(1).to('lemon'));
}, 'Converting a CSSUnitValue to an invalid unit throws SyntaxError');

test(() => {
  assert_throws_js(TypeError, () => new CSSMathMax(1, CSS.px(1)).to('number'));
}, 'Converting a CSSNumericValue with invalid sum value throws TypeError');

test(() => {
  assert_throws_js(TypeError, () => new CSSMathProduct(CSS.px(1), CSS.s(1)).to('number'));
}, 'Converting a CSSNumericValue with sum value containing more than one value throws TypeError');

test(() => {
  assert_throws_js(TypeError, () => CSS.px(1).to('number'));
}, 'Converting a CSSUnitValue to an incompatible unit throws TypeError');

test(() => {
  for (const unit of gValidUnits) {
    // FIXME(778495): Remove this check onec all the units are supported.
    if (CSS[unit])
      assert_style_value_equals(CSS[unit](1).to(unit), CSS[unit](1));
  }
}, 'Converting a CSSUnitValue to its own unit returns itself');

// TODO(776173): cssUnitValue_toMethod.html has more comprehensive tests of converting
// within the same base type. Merge those tests into here.
test(() => {
  assert_style_value_equals(CSS.cm(1).to('px'), CSS.px(37.7952755));
}, 'Converting a CSSUnitValue to its canonical unit returns correct value');

test(() => {
  assert_style_value_equals(new CSSMathSum(CSS.px(1), CSS.px(1)).to('px'), CSS.px(2));
  assert_style_value_equals(new CSSMathSum(CSS.px(1), CSS.px(1), CSS.px(1)).to('px'), CSS.px(3));
}, 'Converting a CSSMathSum to a single unit adds the values');

test(() => {
  assert_style_value_equals(new CSSMathProduct(CSS.px(2), 3).to('px'), CSS.px(6));
  assert_style_value_equals(new CSSMathProduct(-1, CSS.px(2), 3).to('px'), CSS.px(-6));
}, 'Converting a CSSMathProduct to a single unit multiplies the values');

test(() => {
  assert_style_value_equals(new CSSMathMin(CSS.cm(1), CSS.mm(1)).to('mm'), CSS.mm(1));
}, 'Converting a CSSMathMin to a single unit finds the min value');

test(() => {
  assert_throws_js(TypeError, () => new CSSMathMin(CSS.px(2), CSS.s(3)).to('px'));
  assert_throws_js(TypeError, () => new CSSMathMin(CSS.px(2), 3).to('px'));
}, 'Converting a CSSMathMin to a single unit with different units throws a TypeError');

test(() => {
  assert_style_value_equals(new CSSMathMax(CSS.cm(1), CSS.mm(1)).to('mm'), CSS.mm(10));
}, 'Converting a CSSMathMax to a single unit finds the max value');

test(() => {
  assert_throws_js(TypeError, () => new CSSMathMax(CSS.px(2), CSS.s(3)).to('px'));
  assert_throws_js(TypeError, () => new CSSMathMax(CSS.px(2), 3).to('px'));
}, 'Converting a CSSMathMax to a single unit with different units throws a TypeError');

test(() => {
  assert_style_value_equals(new CSSMathNegate(CSS.px(1)).to('px'), CSS.px(-1));
}, 'Converting a CSSMathNegate to a single unit negates its value');

test(() => {
  const expr = new CSSMathProduct(CSS.px(4), new CSSMathInvert(CSS.px(2)));
  assert_style_value_equals(expr.to('number'), CSS.number(2));
}, 'Converting a CSSMathInvert to a single unit inverts its value and units');

test(() => {
  // max((1s * 1s *  1px * 1px) / (1s * 1px), 2000ms * 2em) / 1em - min(500ms, 1s)
  const expr = new CSSMathSum(
    new CSSMathProduct(
      new CSSMathMax(
        new CSSMathProduct(
          new CSSMathProduct(CSS.s(1), CSS.s(1), CSS.px(1), CSS.px(1)),
          new CSSMathInvert(new CSSMathProduct(CSS.s(1), CSS.px(1))),
        ),
        new CSSMathProduct(CSS.ms(2000), CSS.cm(2))
      ),
      new CSSMathInvert(CSS.cm(1))
    ),
    new CSSMathNegate(
      new CSSMathMin(
        CSS.ms(500),
        CSS.s(1)
      )
    )
  );

  assert_style_value_equals(expr.to('ms'), CSS.ms(3500));
}, 'Converting a complex expression to a single unit');

</script>
